﻿using System.Net.Http;
using System.Text.Json;
using DataManageSystem.Models;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;

namespace DataManageSystem.Services.backservices
{
    public class NacosServiceMonitorService : BackgroundService
    {
        private readonly ILogger<NacosServiceMonitorService> _logger;
        private readonly IServiceScopeFactory _scopeFactory;
        private static readonly HttpClient _httpClient = new(); // 单例 HttpClient
        private readonly List<string> _expectedServices = new()
        {
            "after-sales",
            "common-service",
            "contract",
            "authority-center",
            "exp-manage",
            "basic-data",
            "consumable-manage",
            "customer",
            "finance",
        };

        private const string _nacosBaseUrl = "http://localhost:8848/nacos/v1/ns";
        private const string _namespaceId = "fc807e1b-1119-4348-95a3-f8c85f1c340c";
        private const string _accessToken =
            "eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJuYWNvcyIsImV4cCI6MTczODgzMjIwNn0.ypOgoKYOtBRLL7b9FNgXtP3L90kvyftSOZZsF6YSgjo";

        public NacosServiceMonitorService(
            ILogger<NacosServiceMonitorService> logger,
            IServiceScopeFactory scopeFactory
        )
        {
            _logger = logger;
            _scopeFactory = scopeFactory;
        }

        protected override async Task ExecuteAsync(CancellationToken stoppingToken)
        {
            _logger.LogInformation("✅ Nacos 服务监控服务启动成功");

            while (!stoppingToken.IsCancellationRequested)
            {
                try
                {
                    var services = await GetServiceListAsync();
                    var missingServices = _expectedServices.Except(services).ToList();

                    using var scope = _scopeFactory.CreateScope();
                    var mailService = scope.ServiceProvider.GetRequiredService<IMailService>();

                    foreach (var missing in missingServices)
                    {
                        _logger.LogError("❌ 缺失服务: {Service}", missing);
                        await SendAlarmEmail(mailService, missing, isMissing: true);
                    }

                    foreach (var service in _expectedServices)
                    {
                        if (services.Contains(service))
                        {
                            bool healthy = await IsServiceHealthyAsync(service);
                            if (healthy)
                            {
                                _logger.LogInformation(
                                    "{Time}: ✅ 运行正常 -> {Service}",
                                    DateTime.Now,
                                    service
                                );
                            }
                            else
                            {
                                _logger.LogError(
                                    "{Time}: ❗服务异常 -> {Service}",
                                    DateTime.Now,
                                    service
                                );
                                await SendAlarmEmail(mailService, service, isMissing: false);
                            }
                        }
                    }
                }
                catch (Exception ex)
                {
                    _logger.LogError("💥 执行服务监控时出错：{Message}", ex.Message);
                }

                await Task.Delay(TimeSpan.FromSeconds(10), stoppingToken);
            }
        }

        private async Task<List<string>> GetServiceListAsync()
        {
            var result = new List<string>();
            try
            {
                var url =
                    $"{_nacosBaseUrl}/catalog/services"
                    + $"?hasIpCount=true&withInstances=false&pageNo=1&pageSize=1000"
                    + $"&namespaceId={_namespaceId}&accessToken={_accessToken}";

                var response = await _httpClient.GetAsync(url);
                response.EnsureSuccessStatusCode();

                using var stream = await response.Content.ReadAsStreamAsync();
                using var doc = await JsonDocument.ParseAsync(stream);

                if (doc.RootElement.TryGetProperty("serviceList", out var serviceList))
                {
                    foreach (var service in serviceList.EnumerateArray())
                    {
                        if (service.TryGetProperty("name", out var name))
                            result.Add(name.GetString()!);
                    }
                }
            }
            catch (Exception ex)
            {
                _logger.LogError("❌ 获取服务列表失败: {Message}", ex.Message);
            }

            return result;
        }

        private async Task<bool> IsServiceHealthyAsync(string serviceName)
        {
            try
            {
                var url =
                    $"{_nacosBaseUrl}/instance/list"
                    + $"?serviceName={serviceName}&namespaceId={_namespaceId}&accessToken={_accessToken}";

                var response = await _httpClient.GetAsync(url);
                response.EnsureSuccessStatusCode();

                using var stream = await response.Content.ReadAsStreamAsync();
                using var doc = await JsonDocument.ParseAsync(stream);

                if (doc.RootElement.TryGetProperty("hosts", out var hosts))
                {
                    foreach (var host in hosts.EnumerateArray())
                    {
                        if (host.TryGetProperty("healthy", out var healthy) && healthy.GetBoolean())
                            return true;
                    }
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(
                    "❌ 检查健康状态失败：{Service} -> {Message}",
                    serviceName,
                    ex.Message
                );
            }

            return false;
        }

        private async Task SendAlarmEmail(
            IMailService mailService,
            string serviceName,
            bool isMissing
        )
        {
            var subject = "【无锡生物所LIMS系统告警】后台服务异常";
            var reason = isMissing ? "未注册" : "健康检查失败";

            var mail = new MailRequest
            {
                To = "lkc@modelinglab.ai",
                Subject = subject,
                Body =
                    $@"系统检测到无锡生物所后台服务存在异常，请尽快排查。
                    服务名称：{serviceName}
                    异常类型：{reason}
                    检测时间：{DateTime.Now:yyyy-MM-dd HH:mm:ss}",
            };



            await mailService.SendEmailAsync(mail);
        }
    }
}
